package dl.bukkit.myststus.function;

import dl.bukkit.myststus.MyStatus;
import dl.bukkit.myststus.function.condition.ICondition;
import dl.bukkit.myststus.function.condition.imp.LevelCondition;
import dl.bukkit.myststus.function.condition.imp.PermissionCondition;
import dl.bukkit.myststus.function.condition.imp.PlaceholderCondition;
import dl.bukkit.myststus.function.trigger.Trigger;
import dl.bukkit.myststus.function.trigger.TriggerHandler;
import dl.bukkit.myststus.function.trigger.imp.*;
import dl.bukkit.myststus.library.ats.GComponent;
import dl.bukkit.myststus.loader.Loader;
import dl.bukkit.myststus.logger.Logger;
import org.bukkit.event.Event;
import org.bukkit.plugin.EventExecutor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class ComponentManager implements Loader {

    private static ComponentManager inst;

    private final MyStatus plugin;

    private final Map<String, ICondition> conditions = new HashMap<>();

    private final Map<String, Trigger<?>> triggers = new HashMap<>();
    private final Map<TriggerHandler, EventExecutor> triggerExecutors = new HashMap<>();
    private final Map<Trigger<?>, TriggerHandler> triggerHandlers = new HashMap<>();

    private ComponentManager(MyStatus plugin) {
        inst = this;
        this.plugin = plugin;
    }

    @Override
    public void onLoad() {
        registerTrigger(ClientTrigger.class);
        registerTrigger(JoinTrigger.class);
        registerTrigger(TaskTrigger.class);
        registerTrigger(HealthTrigger.class);
        registerTrigger(ReloadTrigger.class);

        registerCondition(LevelCondition.class);
        registerCondition(PermissionCondition.class);
        registerCondition(PlaceholderCondition.class);
    }

    @Override
    public void staring() {
        triggerHandlers.values().forEach(handler -> handler.registerEvent(plugin));
    }

    public static void registerCondition(Class<? extends ICondition> cls) {
        try {
            Constructor<? extends ICondition> constructor = cls.getDeclaredConstructor();
            GComponent annotation = cls.getAnnotation(GComponent.class);
            if (annotation == null) {
                Logger.consoleMessage("§c", "register failure,", cls.getSimpleName(), ".class annotation is null");
                return;
            }
            Logger.debug("§a组件§6[§f", annotation.key(), "§6]: ");
            Logger.debug("  §3类型: §f条件限制");
            ICondition iCondition = constructor.newInstance();
            boolean register = iCondition.isRegister();
            if (register) {
                inst.conditions.put(annotation.key().toLowerCase(), iCondition);
            }
            Logger.debug("  §3是否启动: §f", register ? "√" : "×");
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unchecked")
    public static <E extends Event> void registerTrigger(Class<? extends Trigger<E>> cls) {
        try {
            Constructor<? extends Trigger<E>> constructor = cls.getDeclaredConstructor();
            GComponent annotation = cls.getAnnotation(GComponent.class);
            if (annotation == null) {
                Logger.consoleMessage("§c", "register failure,", cls.getSimpleName(), ".class annotation is null");
                return;
            }
            Logger.debug("§a组件§6[§f", annotation.key(), "§6]: ");
            Logger.debug("  §3类型: §f触发器");
            Trigger<E> trigger = constructor.newInstance();
            boolean register = trigger.isRegister();
            if (register) {
                TriggerHandler handler = new TriggerHandler(trigger);
                inst.triggers.put(annotation.key().toLowerCase(), trigger);
                inst.triggerHandlers.put(trigger, handler);
                inst.triggerExecutors.put(handler, (listener, event) -> ((TriggerHandler) listener).apply((E) event, trigger, inst.plugin));
            }
            Logger.debug("  §3是否启动: §f", register ? "√" : "×");
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static Trigger<?> getTrigger(String key) {
        return inst.triggers.get(key.toLowerCase());
    }

    public static EventExecutor getTriggerExecutor(TriggerHandler handler) {
        return inst.triggerExecutors.get(handler);
    }

    public static TriggerHandler getTriggerHandler(Trigger<?> component) {
        return inst.triggerHandlers.get(component);
    }

    public static ICondition getCondition(String key) {
        return inst.conditions.get(key.toLowerCase());
    }
}

